// Frustum
// (c) jimon game studio

#ifndef JEH_JEFRUSTUM
#define JEH_JEFRUSTUM

#include "jeTypes.h"
#include "jeStl.h"
#include "jeUnknown.h"

namespace je
{
	namespace scene
	{
		//! Frustum
		class jeFrustum:public je::jeUnknown
		{
		private:
			//Frustum Data
			jePlane Planes[6];
		public:

			//! Constructor
			jeFrustum()
			{
			}

			//! Destructor
			~jeFrustum()
			{
			}

			//! Calculate Frustum
			void CalculateFrustum(const jeMatrix4f & Proj,const jeMatrix4f & Modv)
			{
				jeMatrix4f Clip = Proj * Modv;

				Planes[0].A = Clip.Get(3,0)-Clip.Get(0,0);
				Planes[0].B = Clip.Get(3,1)-Clip.Get(0,1);
				Planes[0].C = Clip.Get(3,2)-Clip.Get(0,2);
				Planes[0].D = Clip.Get(3,3)-Clip.Get(0,3);

				Planes[1].A = Clip.Get(3,0)+Clip.Get(0,0);
				Planes[1].B = Clip.Get(3,1)+Clip.Get(0,1);
				Planes[1].C = Clip.Get(3,2)+Clip.Get(0,2);
				Planes[1].D = Clip.Get(3,3)+Clip.Get(0,3);

				Planes[2].A = Clip.Get(3,0)+Clip.Get(1,0);
				Planes[2].B = Clip.Get(3,1)+Clip.Get(1,1);
				Planes[2].C = Clip.Get(3,2)+Clip.Get(1,2);
				Planes[2].D = Clip.Get(3,3)+Clip.Get(1,3);

				Planes[3].A = Clip.Get(3,0)-Clip.Get(1,0);
				Planes[3].B = Clip.Get(3,1)-Clip.Get(1,1);
				Planes[3].C = Clip.Get(3,2)-Clip.Get(1,2);
				Planes[3].D = Clip.Get(3,3)-Clip.Get(1,3);

				Planes[4].A = Clip.Get(3,0)-Clip.Get(2,0);
				Planes[4].B = Clip.Get(3,1)-Clip.Get(2,1);
				Planes[4].C = Clip.Get(3,2)-Clip.Get(2,2);
				Planes[4].D = Clip.Get(3,3)-Clip.Get(2,3);

				Planes[5].A = Clip.Get(3,0)+Clip.Get(2,0);
				Planes[5].B = Clip.Get(3,1)+Clip.Get(2,1);
				Planes[5].C = Clip.Get(3,2)+Clip.Get(2,2);
				Planes[5].D = Clip.Get(3,3)+Clip.Get(2,3);

				for(int i = 0; i < 6; i++)
				{
					f32 t = jeInvSqr(Planes[i].A * Planes[i].A + Planes[i].B * Planes[i].B + Planes[i].C * Planes[i].C);
					Planes[i].A *= t;
					Planes[i].B *= t;
					Planes[i].C *= t;
					Planes[i].D *= t;
				}
			}

			//! Return True if sphere in frusum
			u1 IsSphereIn(const jeVector3df & Pos,f32 R)
			{
				for(int i = 0; i < 6; i++)
					if(Planes[i].GetDistance(Pos) < -R)
						return false;

				return true;
			}

			//! Return True if point in frusum
			u1 IsPointIn(const jeVector3df & Pos)
			{
				for(int i = 0; i < 6; i++)
					if(Planes[i].GetDistance(Pos) < 0)
						return false;

				return true;
			}

		};
	}
}

#endif
